﻿package  
{
	import flash.display.MovieClip;
	import flash.geom.Point;
	import flash.system.ApplicationDomain;
	
	/**
	 * ...
	 * @author kot
	 * 
	 * Какого хрена method overloading не реализован в actionscript?
	 */
	public class Board extends MovieClip {
		var size = 50;
		var cells:Array = new Array(8);
		var horizName:Array =  new Array( "a", "b", "c", "d", "e", "f", "g", "h" );
		var vertName:Array  =  new Array ("1", "2", "3", "4", "5", "6", "7", "8");
		var PawnW:Class;
		var PawnB:Class;
		var RockW:Class;
		var RockB:Class;
		var KnigthW:Class;
		var KnigthB:Class;
		var BishopW:Class;
		var BishopB:Class;
		var QueenW:Class;
		var QueenB:Class;
		var KingW:Class;
		var KingB:Class;
		private var whiteMove : int = 1;
		
		public static var Field:Class = ApplicationDomain.currentDomain.getDefinition("Field") as Class;
		
		var connection: Connection;

		
		var fogCells:    Array = new Array();
		var whitePieces: Array = new Array("Pa2","Pb2","Pc2","Pd2", "Pe2","Pf2","Pg2","Ph2","Ra1","Rh1","Nb1","Ng1","Bc1","Bf1","Qd1","Ke1");
		var blackPieces: Array = new Array("Pa7", "Pb7", "Pc7","Pd7","Pe7","Pf7","Pg7","Ph7","Ra8","Rh8","Nb8","Ng8","Bc8","Bf8","Qd8","Ke8");
		
		//constructor
		public function Board(con:Connection) 
		{		
			connection = con;

			
			///////////////////////
			//    init figure classes
			///////////////////////
			PawnW  = ApplicationDomain.currentDomain.getDefinition("PawnWhite") as Class;
			PawnB  = ApplicationDomain.currentDomain.getDefinition("PawnBlack") as Class;
			RockW  = ApplicationDomain.currentDomain.getDefinition("RockWhite") as Class;
			RockB  = ApplicationDomain.currentDomain.getDefinition("RockBlack") as Class;
			KnigthW= ApplicationDomain.currentDomain.getDefinition("KnigthWhite") as Class;
			KnigthB= ApplicationDomain.currentDomain.getDefinition("KnigthBlack") as Class;
			BishopW= ApplicationDomain.currentDomain.getDefinition("BishopWhite") as Class;
			BishopB= ApplicationDomain.currentDomain.getDefinition("BishopBlack") as Class;
			QueenW = ApplicationDomain.currentDomain.getDefinition("QueenWhite") as Class;
			QueenB = ApplicationDomain.currentDomain.getDefinition("QueenBlack") as Class;
			KingW  = ApplicationDomain.currentDomain.getDefinition("KingWhite") as Class;
			KingB  = ApplicationDomain.currentDomain.getDefinition("KingBlack") as Class;
			
			
			//y - строчка
			//x - столбец
			var yy = -size;
			for (var y = 7; y >= 0; y--) {
				yy += size;
				var tmpArray : Array = new Array(8);
				var xx = 0;
				for (var x = 0; x < 8; x++) {
					tmpArray[x] = new Field();
					tmpArray[x].size = size;
					tmpArray[x].x = xx;
					tmpArray[x].y = yy;
					tmpArray[x].name = horizName[x] + vertName[y];
					tmpArray[x].isWhite = (x % 2) !=  (y % 2);
					tmpArray[x].setAvaliable(false);
					tmpArray[x].reDraw();
					tmpArray[x].nameX = x;
					tmpArray[x].nameY = y;
					///
					xx += size;
					addChild(tmpArray[x]);
				}
				cells[y] = tmpArray;
			}
			
			//set fog
			
			for (var tmp in fogCells) {
				getCellByString(fogCells[tmp]).setFog(true);
				//cells[fogCells[tmp].charCodeAt(0) - String("a").charCodeAt(0)][fogCells[tmp].charCodeAt(1) - String("1").charCodeAt(0)].setFog(true);
			}
			

			//figure init
			initFigures(whitePieces, true);
			initFigures(blackPieces, false);	
			changeMove();
			searchForOpp();
		}
		
		/////////////////////////
		//figure initialization
		/////////////////////////
		function initFigures(colorPiece:Array, isWhite : Boolean) {
			for (var k = 0 ; k < colorPiece.length; ++k) {
				var newPiece: Figure;
				switch(colorPiece[k].charAt(0)) {
					case "R":
						if (isWhite)
							newPiece = new RockW(); 
						else
							newPiece = new RockB();
						break;
					case "B":
						if (isWhite)
							newPiece = new BishopW(); 
						else 
							newPiece = new BishopB();
						break;
					case "N":
						if (isWhite)
							newPiece = new KnigthW();
						else
							newPiece = new KnigthB();
						break;
					case "Q":
						if (isWhite)
							newPiece = new QueenW();
						else 
							newPiece = new QueenB();
						break;
					case "K":
						if (isWhite)
							newPiece = new KingW();
						else 
							newPiece = new KingB();
						break;
					case "P":
						if (isWhite)
							newPiece = new PawnW();
						else 
							newPiece = new PawnB();
						break;
					default:
						throw Error("unknown piece");
				}
				//newPiece.name = colorPiece[k];
				if (isWhite)
					newPiece.setFigureColor(2) else
					//TODO set constants
					newPiece.setFigureColor(1);
				newPiece.figureY = colorPiece[k].charCodeAt(2) - String("1").charCodeAt(0);
				newPiece.figureX = colorPiece[k].charCodeAt(1) - String("a").charCodeAt(0);
				getCellByString(colorPiece[k].substr(1,2)).addFigure(newPiece);
				addChild(newPiece);
			}
		}
		
		//don't know what it does
		function searchForOpp() {
			
		}
		
		//////////////////////////
		//trace the moves
		///////////////////////
		function move(fromWhereToWhere : String):void {
			trace(fromWhereToWhere);
		}

		
		function getCellByString(n : String) : Cell {
			var tmpY : int = n.charCodeAt(0) - String("a").charCodeAt(0);
			var tmpX : int = n.charCodeAt(1) - String("1").charCodeAt(0);
			return (cells[tmpX][tmpY]);
		}
		
		function getCell(x : int, y : int) : Cell {
			return cells[y][x];
		}
		
		function resetCells():void {
			for (var y  = 0; y < 8; y++) {
				for (var x = 0; x < 8; x++) {
					cells[y][x].setAvaliable(false);
				}
			}
		}
		
		///////////////////////////////////
		////Changes moves
		///////////////////////////////////
		function changeMove() : void {
			whiteMove = 1 + whiteMove % 2;			
			var availableMoves : int = 0;
			if (!positionOK())
				trace("check!");
			for (var x = 0; x < 8; ++x) {
				for (var y = 0; y < 8; ++y) {
					//for every figure 
					///select, if we can move
					var fig : Figure = getCell(x, y).getFigure();
					if (fig == null) {
						continue;
					}
					if (fig.getFigureColor() == whiteMove) {
						fig.getAvailableMoves();
						var moves : Array = fig.moves;
						fig.resetMoves();	
						///take all moves we can
						///and for every move check:
						///if that move is possible, we push it to fig.moves
						for (var i = 0; i < moves.length; ++i) {
							var moveCell :Cell = getCell(moves[i].x, moves[i].y);
							var pawnedFig : Figure = moveCell.getFigure();
							moveCell.removeFigure();
							getCell(x, y).removeFigure();
							moveCell.addFigure(fig);
							if (positionOK()) {
								fig.moves.push(moves[i]);
								availableMoves++;
							}
							getCell(x, y).addFigure(fig);
							moveCell.removeFigure();
							moveCell.addFigure(pawnedFig);
						}
					}
				}
			}
			if (availableMoves == 0) {
				trace("No moves");
			}
		}
		
		private function getKing(figureColor : int) : Point {
			for (var i = 0; i < 8; i++) {
				for (var j = 0; j < 8; j++) {
					if (getCell(i, j).getFigure() == null)
						continue;
					if (getCell(i, j).getFigure().toString() == "King" && 
						getCell(i, j).getFigure().getFigureColor() == figureColor) {
							return new Point(i, j);
						}
				}
			}
			return null;
		}
		
		public function positionOK() : Boolean {
			return checkCellIsOk(getKing(whiteMove), whiteMove);
		}
		
		
		/**
		 * checks, if figure can move/eat to that cell
		 * @param	cell checked Cell
		 * @param	figColor
		 * @return
		 */
		public function checkCellIsOk(cell : Point, figColor : int) :Boolean {
			if (cell == null) 
				return false;
			var enemyColor : int = 1 + whiteMove % 2;
			for (var i = 0; i < 8; i++) {
				for (var j = 0; j < 8; j++) {
					var fig : Figure = getCell(i, j).getFigure();
					if (fig == null) {
						continue;
					}
					if (fig.getFigureColor() == enemyColor && fig.canMove(cell.x, cell.y)) {
						return false;
					}
				}
			}
			return true;
		}
		
		/**
		 * 
		 *checks for move order 
		 * 
		 * @return 1 if white
		 * @return 2 if black
		 */
		public function getMove() : int {
			return whiteMove;
		}
	}

}